package com.spzx.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.spzx.common.security.utils.SecurityUtils;
import com.spzx.product.bitmap.BitmapSyncService;
import com.spzx.product.domain.Product;
import com.spzx.product.domain.ProductDetails;
import com.spzx.product.domain.ProductSku;
import com.spzx.product.domain.SkuStock;
import com.spzx.product.mapper.ProductDetailsMapper;
import com.spzx.product.mapper.ProductMapper;
import com.spzx.product.mapper.ProductSkuMapper;
import com.spzx.product.mapper.SkuStockMapper;
import com.spzx.product.service.ProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spzx.product.vo.ProductVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品 服务实现类
 * </p>
 *
 * @author lynn
 * @since 2025-03-12
 */
@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ProductSkuMapper productSkuMapper;
    @Autowired
    private SkuStockMapper skuStockMapper;
    @Autowired
    private ProductDetailsMapper productDetailsMapper;
    @Autowired
    private BitmapSyncService bitmapSyncService;

    @Override
    public List<ProductVo> selectProductList() {
        return productMapper.selectProductList();
    }

    @Override
    @Transactional(rollbackFor = Exception.class) //只能支持数据库事务回滚，不支持redis事务回滚
    public int insertProduct(Product product) {
        //往商品表插入数据
        productMapper.insert(product);

        List<ProductSku> productSkuList = product.getProductSkuList();
        for (int i = 0; i < productSkuList.size(); i++) {
            //往商品sku表插入数据
            ProductSku productSku = productSkuList.get(i);
            productSku.setSkuCode(product.getId() + "_" + i);
            productSku.setProductId(product.getId());
            String skuName = product.getName() + " " + productSku.getSkuSpec();
            productSku.setSkuName(skuName);
            productSku.setStatus(0);
            productSkuMapper.insert(productSku);


            //添加商品库存
            SkuStock skuStock = new SkuStock();
            skuStock.setSkuId(productSku.getId());
            skuStock.setTotalNum(productSku.getStockNum());
            skuStock.setLockNum(0);
            skuStock.setAvailableNum(productSku.getStockNum());
            skuStock.setSaleNum(0);
            skuStockMapper.insert(skuStock);
        }
        ProductDetails productDetails = new ProductDetails();
        productDetails.setProductId(product.getId());
        productDetails.setImageUrls(String.join(",", product.getDetailsImageUrlList()));
        productDetailsMapper.insert(productDetails);


        //由于添加商品库存时库存状态默认为0(未上架) 不需要更新bitmap

        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateStatus(Long id, Integer status) {
        List<Long> skuIdList = productSkuMapper.selectList(
                        new LambdaQueryWrapper<ProductSku>()
                                .eq(ProductSku::getProductId, id)
                                .select(ProductSku::getId)
                ).stream()
                .map(ProductSku::getId)
                .collect(Collectors.toList());
        //更新product表中的status字段
        Product product = new Product();
        product.setId(id);
        product.setStatus(status);
       product.setUpdateBy(SecurityUtils.getUsername());
        productMapper.updateById(product);

        //更新product_sku表中的status字段
        productSkuMapper.update(null,new LambdaUpdateWrapper<ProductSku>().eq(ProductSku::getProductId,id).set(ProductSku::getStatus,status));

        // 事务提交后更新 Bitmap
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                /**
                 * 在事务提交后查询数据库在并发情况下会导致 数据不一致的问题 所以需要在上面记录newSkuIds
                 */
/*                List<Long> skuIdList = productSkuMapper.selectList(new LambdaQueryWrapper<ProductSku>().eq(ProductSku::getProductId, id))
                        .stream().map(ProductSku::getId).toList();*/

                skuIdList.forEach(skuId ->
                        bitmapSyncService.updateBitmap(skuId, status == 1) // true 表示上架，false 表示下架
                );
            }
        });
        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeBatchIds(List<Long> ids) {
        //stu_stock
        for (Long id : ids){
            //先查product对应的sku_id
            List<ProductSku> productSkuList = productSkuMapper.selectList(new LambdaUpdateWrapper<ProductSku>().eq(ProductSku::getProductId, id));

            for (ProductSku productSku : productSkuList) {
                //再根据sku_id删除stu_stock
                skuStockMapper.delete(new LambdaUpdateWrapper<SkuStock>().eq(SkuStock::getSkuId, productSku.getId()));

                //从bitmap中设置对应skuId为false
                bitmapSyncService.updateBitmap(productSku.getId(),false);
            }

        }
        //批量删除
        productMapper.deleteBatchIds(ids);
        productSkuMapper.delete(new LambdaUpdateWrapper<ProductSku>().in(ProductSku::getProductId,ids));
        productDetailsMapper.delete(new LambdaUpdateWrapper<ProductDetails>().in(ProductDetails::getProductId,ids));

        // 事务提交后更新 Bitmap
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                List<Long> newSkuIds = productSkuMapper.selectList(new LambdaQueryWrapper<ProductSku>().in(ProductSku::getProductId, ids))
                        .stream().map(ProductSku::getId).toList();
                newSkuIds.forEach(skuId ->
                        bitmapSyncService.updateBitmap(skuId, false)
                );
            }
        });
        return 1;
    }
}
